package com.ce.source.analysis.queue;

import java.util.Iterator;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;

/**
 * @author ：xiaopingzhang8@creditease.cn
 * @Description ：队列分析
 * @ClassName ：BlockQueueAnalyse
 * @Company ：普信恒业科技发展（北京）有限公司
 * @date ：2017/11/27 18:14
 */

/**
 * <p>
 *     <h2>LinkedBlockingQueue取值，赋值对应关系</h2>
 *     <ol>
 *         <li style="color:red">put<==>take</li>线程会阻塞
 *         <li style="color:green">offer<==>poll</li>通过设置超时时间防止线程阻塞
 *     </ol>
 * </p>
 */
public class BlockQueueAnalyse {
    public static void main(String[] args) {
//        analysePut();
//        analyseTake();
//        analyseOffer();
        analyseIterator();
    }

    /**
     * put方法分析
     * <p>
     * <ol>
     * <li>
     * 初始化LinkedBlockingQueue的容量，默认Integer.MAX_VALUE
     * </li>
     * <li>
     * 初始化Node节点
     * </li>
     * <li>
     * 获取锁reentrantLock（可重入锁）；原子变量计数器AtomicInteger；设置锁可中断，防止死锁
     * </li>
     * <li>
     * 插入Node节点
     * </li>
     * <li>
     * 设置信号量signalNotEmpty
     * </li>
     * <li>
     * 插入节点超过容量，进入等待notFull.await()
     * </li>
     * <p>
     * </ol>
     * </p>
     */
    public static void analysePut() {
        LinkedBlockingQueue<Object> queue = new LinkedBlockingQueue<Object>(4);
        try {
            queue.put(1);
            queue.put(2);
            queue.put(3);
            queue.put(4);
            queue.put(5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * take方法分析
     * <p>
     *     <ol>
     *         <li>
     *            队列中有数据，并且唤醒了队列不为空的信号量signalNotEmpty
     *         </li>
     *         <li>
     *            获得takeLock锁
     *         </li>
     *         <li>
     *             head.next 出队列，head后移 head.item=null
     *         </li>
     *         <li>
     *             长度减一
     *         </li>
     *         <li>
     *             如果队列为空，take()线程进入等待中……notEmpty.await()
     *         </li>
     *     </ol>
     * </p>
     */
    public static void analyseTake() {
        LinkedBlockingQueue<Object> queue = new LinkedBlockingQueue<Object>(4);
        try {
            queue.put(1);
            queue.put(2);
            queue.put(3);
            queue.put(4);
            System.out.println("take->" + queue.take());
            queue.put(5);
            while (!queue.isEmpty()) {
                System.out.println("take->" + queue.take());
            }
            queue.take();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * 分析offer方法
     * <p>
     *     <h2>offer(E e)方法实现跟put(E e)基本一致</h2>
     *     <h2>区别方法offer(E e, long timeout, TimeUnit unit)</h2>
     *     <ol>
     *         <li>如果队列满了，插入数据不会阻塞，等待一段时间后返回false</li>
     *     </ol>
     * </p>
     */
    public static void analyseOffer(){
        LinkedBlockingQueue<Object> queue = new LinkedBlockingQueue<Object>(4);
        try {
            queue.offer(1);
            queue.offer(2);
            queue.offer(3);
            queue.offer(4);
            queue.offer(5,5, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void analyseIterator(){
        LinkedBlockingQueue<Object> queue = new LinkedBlockingQueue<Object>(4);
        try {
            queue.offer(1);
            queue.offer(2);
            queue.offer(3);
            queue.offer(4);
            queue.offer(5,5, TimeUnit.SECONDS);
            Iterator<Object> it = queue.iterator();
            while (it.hasNext()){
                System.out.println("it->"+it.next());
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
